import base64
import pickle

from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from goods.models import SKU
from .serializers import CartSerializer
# Create your views here.

class CartView(GenericAPIView):
    serializer_class = CartSerializer

    # 重写方法,让未登录用户也能访问视图
    def perform_authentication(self, request):
        pass

    # 购物车添加商品
    def post(self, request):
        # 获取数据
        dict_data = request.data

        # 获取序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 获取数据
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected', True)
        try:
            user = request.user
        except Exception as e:
            user = None

        # 判断用户状态
        if user and request.user.is_authenticated:
            # 获取redis对象
            redis_conn = get_redis_connection('cart')
            # 增加购物车商品数量
            redis_conn.hincrby('cart_%s' % user.id, sku_id, count)
            # 判断是否选中
            if selected:
                redis_conn.sadd('cart_selected_%s' % user.id, sku_id)
            return Response(serializer.data)
        else:
            # 5.1获取cookie购物车数据
            cookie_cart = request.COOKIES.get('cart')
            # 5.2判断是否有购物车数据
            cookie_dict = {}
            if cookie_cart:
                # pickle.dumps(dict) 将字典数据转换为byte
                # pickle.loads(byte) 将byte转换为字典数据
                # base64.b64.encode(byte) 将8位二进制数据转换为6位二进制数据
                # base64.b64.decode(byte) 将6位二进制数据转换为8位二进制数据
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
            # 5.3累加
            if sku_id in cookie_dict:
                count += cookie_dict[sku_id].get('count', 0)

            # 5.4设置新的数据到字典
            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 5.5将字典转换为字符串写入cookie
            response = Response(status=status.HTTP_200_OK)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie('cart', cookie_cart)

            return response

    # 获取购物车商品
    def get(self, request):
        # 1.获取用户数据
        try:
            user = request.user
        except Exception as e:
            user = None
        # 2.判断用户登陆状态
        if user and request.user.is_authenticated:
            # 2.1获取redis中用户购物车数据
            redis_conn = get_redis_connection('cart')
            redis_cart_dict = redis_conn.hgetall('cart_%s' % user.id)
            redis_cart_selected_list = redis_conn.smembers('cart_selected_%s' % user.id)

            # 2.2 数据拼接
            sku_list = []
            for sku_id, count in redis_cart_dict:
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    'selected': sku_id in redis_cart_selected_list,
                    'default_image_url': sku.default_image_url,
                    'name': sku.name,
                    'price': sku.price,
                    'count': int(count),
                    'id': sku.id
                }
                sku_list.append(sku_dict)
            # 2.3 返回响应
            return Response(sku_list)
        # 3.获取购物车-未登录用户
        else:
            # 3.1获取cookie中的数据
            cookie_cart = request.COOKIES.get('cart')
            # 3.2 转换成字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 3.3 拼接数据
            sku_list = []
            for sku_id , count_selected in cookie_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    'selected': count_selected['selected'],
                    'default_image_url': sku.default_image_url,
                    'name': sku.name,
                    'price': sku.price,
                    'count': count_selected['count']
                }
                sku_list.append(sku_dict)

            return Response(sku_list)

    def put(self, request):
        # 获取参数
        dict_data = request.data
        # 获取序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 获取数据
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')
        try:
            user = request.user
        except Exception as e:
            user = None
        # 判断用户登陆状态
        if user and request.user.is_authenticated:
            # 获取redis数据
            redis_conn = get_redis_connection('cart')

            # 修改redis数据
            redis_conn.hset('cart_%s' % user.id, sku_id, count)
            if selected:
                redis_conn.sadd('cart_selected_%s' % user.id, sku_id)
            else:
                redis_conn.srem('cart_selected_%s' % user.id, sku_id)
            # 返回
            return Response(serializer.data)
        else:
            # 修改未登录用户的cookie数据
            # a.获取cookie数据
            cookie_cart = request.COOKIES.get('cart')
            # b.转换字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
            # c.修改
            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }
            # d.转换成字符串返回
            response = Response(serializer.data)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie('cart', cookie_cart)

            return response

    def delete(self, request):
        """
        删除购物车
        :param request:
        :return:
        """
        # 获取参数
        dict_data = request.data
        # 创建序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 获取数据
        sku_id = serializer.data.get('sku_id')

        try:
            user = request.user
        except Exception as e:
            user = None
        # 判断用户登陆状态
        if user and request.user.is_authenticated:
            # 删除redis中的数据
            redis_conn = get_redis_connection('cart')
            redis_conn.srem('cart_selected_%s' % user.id, sku_id)
            redis_conn.hdel('cart_%s' % user.id, sku_id)
            # 返回响应
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            """
            删除cookie中的购物车数据
            """
            # 获取cookie中的数据
            cookie_cart = request.COOKIES.get('cart')
            # 转换字典
            cookie_dict = {}
            cookie_dict = pickle.loads(base64.b64.decode(cookie_cart.encode()))
            # 删除
            if sku_id in cookie_dict:
                del cookie_dict[sku_id]
            # 返回响应
            response = Response(status=status.HTTP_204_NO_CONTENT)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie('cart', cookie_cart)
            return response






